<template>
  <div class="NTFlowList" ref="wrapper">
    <div class="NTFlowContent" ref="content">
      <div class="NTFlowItem" v-for="(item, index) in list" :key="index" v-slide>
        <slot name="item" :index="index" :item="item"></slot>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, withDefaults } from 'vue';
import { useSlideIn } from '../hooks';

const props = withDefaults(
  defineProps<{
    list: any[];
    slide?: boolean;
    columnWidth?: number; // 列宽
    columnGap?: number; // 列间距
  }>(),
  {
    slide: true,
    columnWidth: 240,
    columnGap: 24,
  }
);

const vSlide = props.slide ? useSlideIn() : {};

const wrapper = ref<HTMLElement | null>(null);
const content = ref<HTMLElement | null>(null);
// waterfall flow 瀑布流列高 [0,0,0,...]
const flowHeight: number[] = [];

/// 绘制瀑布流
const flowDraw = () => {
  if (!content.value) return;
  // 初始化列高
  const columnCount = getColumnCount();
  flowHeight.length = columnCount;
  for (let i = 0; i < columnCount; i++) {
    flowHeight[i] = 0;
  }
  // 设置容器宽（居中布局）
  content.value.style.width =
    (props.columnWidth + props.columnGap) * columnCount - props.columnGap + 'px';

  // 绘制 item
  const doms = content.value.querySelectorAll('.NTFlowItem');
  doms.forEach((dom: any) => {
    const minIdx = getMinIndex(flowHeight);
    dom.style.left = `${minIdx * (props.columnWidth + props.columnGap)}px`;
    dom.style.top = `${flowHeight[minIdx]}px`;
    flowHeight[minIdx] += dom.offsetHeight;
  });
  // 设置容器高
  content.value.style.height = Math.max(...flowHeight) + 'px';
};

/// 获取列数量
const getColumnCount = (): number => {
  if (!wrapper.value) return 0;
  const num = (wrapper.value.offsetWidth + props.columnGap) / (props.columnWidth + props.columnGap);
  return Math.min(Math.floor(num), props.list.length);
};

/// 获取最小值的索引 index
const getMinIndex = (list: number[]) => {
  const min = Math.min(...list);
  return list.indexOf(min);
};

/// 监听窗口变化重绘瀑布流布局
let timer: number | null = null;
const onResize = () => {
  if (timer) {
    clearTimeout(timer);
    timer = null;
  }
  timer = setTimeout(() => {
    flowDraw();
  }, 300);
};

onMounted(() => {
  flowDraw();
  window.addEventListener('resize', onResize);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', onResize);
});
</script>

<style lang="sass" scoped>
.NTFlowContent
  margin-left: auto
  margin-right: auto
  position: relative

.NTFlowItem
  padding-bottom: 24px
  width: v-bind("columnWidth + 'px'")
  position: absolute
  top: 0
  left: 0
</style>
